/*
 * CoreEngineReceiver.java
 */
package org.sunspotworld.demo;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Enumeration;
import java.util.Hashtable;
import org.sunspotworld.executor.DataExecutor;
import org.sunspotworld.manager.DTNManager;

/**
 * This class is starting point of the Core-Engine Receiver application
 * @author Laili Aidi - aidi@kth.se
 * Condroid Summer CSD 2011 - KTH
 */
public class CoreEngineReceiver {

    private DataExecutor obDataExecutor;
    private DTNManager obDTNManager;
    // Duration (in milliseconds) for which to collect samples.
    private static final int FILE_DURATION = 60000;
    //The PATH of this DTN FILE, THIS SHOULD BE DYNAMIC / SET BY USER */
    private String obStrIncomingPath;
    /* The dtnd path of the DTN node, THIS SHOULD BE DYNAMIC / SET BY USER */
    private String obStrDtndPath;
    /* The dtnd conf of the DTN node, THIS SHOULD BE DYNAMIC / SET BY USER */
    private String obStrDtnConfPath;

    /**
     * Start up the host application.
     * Running application:
     * java -jar "/Development Workspace/Workspace/JAVA/WSNDTNCoreEngine-Receiver/dist/WSNDTNCoreEngine-Receiver.jar"
     * 
     * @param args any command line arguments: -p <incoming_path> -dtnd <dtnd_path> -conf <dtnconf_path>
     * @throws Exception  
     */
    public static void main(String[] args) throws Exception {
        CoreEngineReceiver app = new CoreEngineReceiver();
        String obStrIncomingPath = "/root/core-engine/incoming";
        String obStrDtndPath = "/root/dtn2/DTN2/daemon/dtnd";
        String obStrDtnConfPath = "/usr/voyagedtn/dtn.conf";

        int i = 0;
        while (i < args.length) {
            if (args[i].equals("-p")) {
                // The INCOMING FILE PATH for the bundle
                if (args[i + 1] != null && args[1 + 1].length() > 0) {
                    obStrIncomingPath = args[3];
                }
                i++;
            } else if (args[i].equals("-dtnd")) {
                // The DTND PATH
                if (args[4] != null && args[4].length() > 0) {
                    obStrDtndPath = args[4];
                }
                i++;
            } else if (args[i].equals("-conf")) {
                // The DTN CONFIGURATION
                if (args[5] != null && args[5].length() > 0) {
                    obStrDtnConfPath = args[3];
                }
                i++;
            }
            i++;
        }
        app.runningControl(obStrIncomingPath, obStrDtndPath, obStrDtnConfPath);
    }
    ReceiverEngine receiverThread;
    boolean currentState;

    private class ReceiverEngine extends Thread {

        private String obStrFileRcvName;

        public ReceiverEngine(String obStrFileRcvName) {

            this.obStrFileRcvName = obStrFileRcvName;
        }

        public void run() {
            //DTN RECEIVE PART
            while (!Thread.currentThread().isInterrupted()) {
                if (currentState) {
                    try {
                        Enumeration e = senderHash.elements();
                        //Check if there is any new data we're receive at the moment
                        while (e.hasMoreElements()) {
                            String rec = (String) e.nextElement();
                            obDTNManager.receiveData(rec, obStrFileRcvName);
                        }
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
    Hashtable senderHash;

    /**
     * This method is used as starting point of the Core-Engine
     * @param obStrIncomingPath
     * @param obStrDtndPath
     * @param obStrDtnConfPath 
     */
    private void runningControl(String obStrIncomingPath, String obStrDtndPath, String obStrDtnConfPath) {
        this.obStrIncomingPath = obStrIncomingPath;
        this.obStrDtndPath = obStrDtndPath;
        this.obStrDtnConfPath = obStrDtnConfPath;
        //Declare the receivers
        this.senderHash = new Hashtable();
        senderHash.put(1, "android.bytewalla.com");
        senderHash.put(2, "voyage2.bytewalla.com");
        senderHash.put(3, "voyage3.bytewalla.com");
        senderHash.put(4, "voyage4.bytewalla.com");

        /* Declare Object for WSN ReceiverEngine first */
        this.obDataExecutor = new DataExecutor();
        this.obDTNManager = new DTNManager(obDataExecutor, this.obStrIncomingPath, this.obStrDtndPath, this.obStrDtnConfPath);

        String line = null;
        String obStrText = "";
        int timespan = 1000; //check the file conten every 1 second
        Long start = System.currentTimeMillis();
        boolean isrunning = false;

        //Set up the database first, if it fails, the entire system should not continue running
        if (setUpDatabase()) {
            //Declare the ReceiverEngine tread
            receiverThread = new ReceiverEngine("wsndtndata");

            //Collect the data from WSN and Distribute to DTN File
            receiverThread.start();
            System.out.println("\nSTARTING ENGINES [" + receiverThread.isAlive() + "]");
            currentState = false;
            while (true) {
                try {
                    if (System.currentTimeMillis() - start > timespan) {
                        RandomAccessFile raf = new RandomAccessFile("/var/www/flag", "r");
                        //RandomAccessFile raf = new RandomAccessFile("flag", "r");
                        //check the flag now
                        obStrText = raf.readLine();
                        raf.close();
                        if (obStrText != null && obStrText.length() > 0) {
                            obStrText.trim();
                            start = System.currentTimeMillis();
                            if (Integer.parseInt(obStrText) == 1 && !currentState) {
                                //Collect the data from DTN File
                                startEngine();
                                //Means we have to START the DTN and WSN service
                                currentState = true;
                                System.out.println("\nSTARTING RECEIVING [" + currentState + "]");
                            } else if (Integer.parseInt(obStrText) == 0 && currentState) {
                                //Means we have to STOP the DTN and WSN service
                                currentState = false;
                                System.out.println("\nSTOPING RECEIVING [" + currentState + "]");
                            }
                        }
                    }
                } catch (FileNotFoundException ex) {
                    System.err.println("ERROR in runningControl 1: " + ex.getMessage() + " while reading running file.");
                } catch (IOException ie) {
                    System.err.println("ERROR in runningControl 2: " + ie.getMessage() + " while reading running file.");
                } catch (Exception e) {
                    System.err.println("ERROR in runningControl 2: " + e.getMessage() + " while reading running file.");
                }
            }
        }
        tearDown();
    }

    /**
     * This method is used to start the Core-Engine
     */
    private void startEngine() {
        //Activate DTN Receive
        if (setUpDTNManager()) {
            obDTNManager.receiveBundle();
        }
        // System.out.println("\nSTARTING ENGINES [" + receiverThread.isAlive() + "]");
    }

    /**
     * This method is used to stop the Core-Engine
     */
    private void stopEngine() {
        try {
            while (receiverThread.isAlive()) {
                receiverThread.interrupt();
            }
        } catch (Exception e) {
            System.err.println("ERROR in stopEngine1 : " + e.getMessage() + " - Can not stop the Engine");
        }

        System.out.println("\nSTOPING ENGINES [" + receiverThread.isAlive() + "]");

        //obDTNManager.stopDTN();
    }

    /**
     * This method is used to set up the database
     * @return isSuccess
     */
    private boolean setUpDatabase() {
        //Connect to WSN Database
        System.out.println("\nStarting Database ... ");
        if (obDataExecutor.connect()) {
            System.out.println("MESSAGE: Connecting to Database was successful");
            return true;
        }
        System.err.println("ERROR: Connecting to Database was fail");
        return false;
    }

    /**
     * This method is used to set up the DTN Manager
     * @return isSuccess
     */
    private boolean setUpDTNManager() {
        if (obDTNManager.startDTN()) {
            System.out.println("MESSAGE: Starting DTN was successful");
            return true;
        }
        System.err.println("ERROR: Starting DTN was fail.");
        return false;
    }

    /**
     * This method is used to teardown the application
     */
    public void tearDown() {
        try {
            stopEngine();
            obDataExecutor.disconnect();
            //obDTNManager.stopDTN();
            System.exit(0);
        } catch (Exception e) {
        }
    }
}
